#pragma once
#include <cstdio>
#include <string>
#include <iostream>
#include<sys/types.h>
#include<unistd.h>
#include <cstdarg>
#include<pthread.h>
#include"LockGuard.hpp"
#include <fstream>
#include <ctime>
#include<time.h>
using namespace std;

std::string logname="log.txt"; 

bool gIsSave=true;

//1.日志等级
enum Level
{
    DEBUG=0,
    INFO,
    WARNING,
    ERROR,
    FATAL
};
//2.日志消息格式
std::string LevelToString(int level)
{
    switch (level)
    {
    case DEBUG:
        return "Debug";
    case INFO:
        return "Info";
    case WARNING:
        return "Warning";
    case ERROR:
        return "Error";
    case FATAL:
        return "Fatal";
    default:
        return "Unkown";
    }
}

void SaveFile(std::string &filename,std::string &message)
{
    // FILE *file=fopen(filename.c_str(),"a");
    // if(file==nullptr){
    //     return;
    // }
    // fwrite(message.c_str(),1,message.size(),file);
    // fclose(file);

    std::ofstream file(filename,std::ios::app);
    if(!file.is_open()){
        return;
    }
    file<<message;
    file.close();
}

std::string GetTimeString()
{
    time_t curr_time=time(nullptr);
    struct tm *form_time=localtime(&curr_time);
    if(form_time==nullptr){
        return "None";
    }
    char time_buffer[64];
    snprintf(time_buffer,sizeof(time_buffer),"%04d-%02d-%02d %02d:%02d:%02d",
        form_time->tm_year+1900,
        form_time->tm_mon+1,
        form_time->tm_mday,
        form_time->tm_hour,
        form_time->tm_min,
        form_time->tm_sec
    );
    return time_buffer;
}

pthread_mutex_t _mutex=PTHREAD_MUTEX_INITIALIZER;
//3.日志消息
void LogMessage(std::string filename,int line,bool isSave,int level ,const char *format,...)
{
    std::string levelstr=LevelToString(level);
    std::string timestr=GetTimeString();
    pid_t pid=getpid();
    char buffer[1024];

    va_list arg;
    va_start(arg,format);
    vsnprintf(buffer,sizeof(buffer),format,arg);
    va_end(arg);
    //std::cout<<levelstr<<":"<<timestr<<":"<<filename<<":"<<line<<":"<<pid<<" "<<buffer<<std::endl;
    
    std::string message;
    message+="[ level:"+levelstr+"] ";
    message+="[ time:"+timestr+"] ";
    message+="[ filename:"+filename+"] ";
    message+="[ line:"+std::to_string(line)+"] ";
    message+="[ pid:"+std::to_string(pid)+"] ";
    message+=buffer;
    message+="\n";

    LockGuard lock(&_mutex);
    
    if(!isSave)
    {
        std::cout<<message;
    }
    else
    {
        SaveFile(logname,message);
    }
}

#define EnableFile() do { gIsSave=true; }while(0)
#define DisableFile() do { gIsSave=false; }while(0)
#define LOG(level,format,...) do{ LogMessage(__FILE__,__LINE__,gIsSave,level,format,##__VA_ARGS__); }while(0)

void Test(int num,...)
{
    va_list args;
    va_start(args,num);
    while(num)
    {
        int data=va_arg(args,int);
        std::cout<<data<<std::endl;
        num--;
    }
    va_end(args);
}